import type { EnumConfig, EnumItem } from '../types/enum'
import { asyncEnum } from '../api'

interface CacheEntry {
  data: EnumItem[]
  timestamp: number
  ttl: number
}

const DEFAULT_TTL = 24 * 60 * 60 * 1000
class EnumManager {
  private cache = new Map<string, CacheEntry>()
  private loadingPromises = new Map<string, Promise<EnumItem[]>>()
  private defaultTTL = DEFAULT_TTL // 默认30分钟缓存

  // 统一的枚举获取方法
  async getEnums(enumKeys: string[], config: EnumConfig = {}): Promise<Record<string, EnumItem[]>> {
    if (!Array.isArray(enumKeys) || enumKeys.length === 0) {
      return {}
    }

    // 检查哪些枚举已经缓存
    const cachedResults: Record<string, EnumItem[]> = {}
    const uncachedKeys: string[] = []

    for (const key of enumKeys) {
      const cached = this.getCachedData(key)
      if (cached) {
        cachedResults[key] = cached
      } else {
        uncachedKeys.push(key)
      }
    }

    // 如果全部都有缓存，直接返回
    if (uncachedKeys.length === 0) {
      return cachedResults
    }

    // 生成批量请求的缓存key
    const batchKey = uncachedKeys.sort().join(',')

    // 检查是否有相同的批量请求在进行中
    const existingPromise = this.loadingPromises.get(batchKey)
    if (existingPromise) {
      const batchResult = await existingPromise
      return { ...cachedResults, ...this.parseBatchResult(uncachedKeys, batchResult) }
    }

    // 发起批量请求
    const loadPromise = this.loadBatchEnums(uncachedKeys)
    this.loadingPromises.set(batchKey, loadPromise)

    try {
      const batchResult = await loadPromise
      const parsedResult = this.parseBatchResult(uncachedKeys, batchResult)

      // 分别缓存每个枚举
      Object.entries(parsedResult).forEach(([key, data]) => {
        this.setCacheData(key, data, config.ttl)
      })

      return { ...cachedResults, ...parsedResult }
    } catch (error) {
      console.error(`❌ 批量枚举获取失败: ${uncachedKeys.join(', ')}`, error)

      // 尝试返回过期缓存
      const fallbackResults: Record<string, EnumItem[]> = {}
      uncachedKeys.forEach(key => {
        const expiredCache = this.getCachedData(key, true)
        if (expiredCache) {
          fallbackResults[key] = expiredCache
        }
      })

      if (Object.keys(fallbackResults).length > 0) {
        return { ...cachedResults, ...fallbackResults }
      }

      throw error
    } finally {
      this.loadingPromises.delete(batchKey)
    }
  }

  // 强制刷新枚举
  async refreshEnums(
    enumKeys: string[],
    config: EnumConfig = {},
  ): Promise<Record<string, EnumItem[]>> {
    if (!Array.isArray(enumKeys) || enumKeys.length === 0) {
      throw new Error('enumKeys 必须是非空数组')
    }

    // 清理缓存和进行中的请求
    enumKeys.forEach(key => {
      this.cache.delete(key)
      this.loadingPromises.delete(key)
    })

    // 清理批量请求的缓存
    const batchKey = enumKeys.sort().join(',')
    this.loadingPromises.delete(batchKey)

    return this.getEnums(enumKeys, config)
  }

  private getCachedData(cacheKey: string, ignoreExpiry = false): EnumItem[] | null {
    const entry = this.cache.get(cacheKey)
    if (!entry) return null

    if (!ignoreExpiry && Date.now() - entry.timestamp > entry.ttl) {
      this.cache.delete(cacheKey)
      return null
    }

    return entry.data
  }

  private setCacheData(cacheKey: string, data: EnumItem[], customTTL?: number): void {
    const ttl = customTTL || this.defaultTTL
    this.cache.set(cacheKey, {
      data,
      timestamp: Date.now(),
      ttl,
    })
  }

  // 批量枚举请求
  private async loadBatchEnums(enumKeys: string[]): Promise<any> {
    const response = await asyncEnum(enumKeys)
    return response.model ? response.model[0] : {}
  }

  // 解析批量请求结果
  private parseBatchResult(enumKeys: string[], batchData: any): Record<string, EnumItem[]> {
    const result: Record<string, EnumItem[]> = {}

    // 假设API返回格式为: { userStatus: [...], userRole: [...] }
    if (typeof batchData === 'object' && batchData !== null) {
      enumKeys.forEach(key => {
        if (batchData[key]) {
          result[key] = this.transformData(batchData[key], undefined, key)
        } else {
          console.warn(`获取字典数据中缺少字段: ${key}`)
          result[key] = []
        }
      })
    } else {
      console.error('批量结果格式错误:', batchData)
      enumKeys.forEach(key => {
        result[key] = []
      })
    }

    return result
  }

  // 数据转换
  private transformData(
    data: any,
    customTransform?: (data: any) => EnumItem[],
    enumKey?: string,
  ): EnumItem[] {
    if (customTransform) {
      return customTransform(data)
    }

    // 默认转换逻辑
    if (Array.isArray(data)) {
      const resultData = data
        .map(item => ({
          label: item.name,
          value: item.enumCode,
          disabled: item.enable !== '1',
          ...item,
        }))
        .sort((a, b) => a.sort - b.sort)
      resultData.unshift({
        label: '全部',
        value: '-1',
      })
      return resultData
    }
    console.warn(`无法转换枚举数据 ${enumKey}:`, data)
    return []
  }

  // 清理过期缓存
  cleanup(): number {
    const now = Date.now()
    let cleanedCount = 0

    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > entry.ttl) {
        this.cache.delete(key)
        cleanedCount++
      }
    }
    return cleanedCount
  }
}

// 导出单例
export const enumManager = new EnumManager()

// 定期清理过期缓存
setInterval(() => {
  enumManager.cleanup()
}, DEFAULT_TTL) // 一天清理一次缓存
